/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_LOADCTRL_
#define	_INC_AK_LOADCTRL_

#include "ak_types.h"
#include "ak_queue.h"
#include "ak_lock.h"

#ifdef __cplusplus
extern "C" {
#endif

#define 	_LC_TYPE_NULL 		0X00
#define 	_LC_TYPE_ABOVE 		0X01
#define 	_LC_TYPE_BELOW 		0X02

/*	---------------------------------------------------------------------------
**	The Overall Description of Load Control.
**  	1. 	Global :
** 	1.1   System Load ?
** 		CPU.
** 		Memory.
** 		I/O.
** 	1.2   APP Load?
**	1.2.1 	Common
**		Protocol's Common Resource Load. 
**	1.2.2 	Dedicate
**		Protocol's Dedicate Resouce Load.
**
**	2. 	Process Flow :
**	2.1   Common Measure.
**	2.1.1 The Control Module will call Each Mod's System Measure. 
**	2.1.2 The Control Module will call Each Mod's Common Measure. 
** 	2.1.3 The Control Module will call Each Mod's Dedicate Measure.
**
**	3. 	Module.
**	3.1  The App's Load is Reflect by Different Mod.
**	3.2  Sys / Common / Dedicate
**   
**	4. 	Agent
**	Agent is an Container of Task/Thread Level in Mix mode.
**	Each Thread will support multi App-Mod, they Register to the same Agent. The Barrier is Task.
**
**	5. 	Manager
**	Manager is an Container of Process Level in Mix mode. & will Interface to the PM. (Performance Manager)
**	All the Agent is Contained by the Manager.
**	Manager will Poll/Statistic the Agent's Measure Report.
**	
**	6. 	Algor
**	Meter (0, 100)
**	Sum = Weight1 * Meter1 + Weight2 * Meter2 + ...... + WeigthN * MeterN
**	Ratio = Sum / (Weight1 + Weight2 + ... WeightN)
**	if (Ratio > Threshold), We'll Alert & Notify.
*/

/*
** Measure 	: CB(void * pArg, long lArg, int index). (Noramlly, Index = Agent->index, | Task Index )
** Notify    	: CB(void * pArg, long lArg, int index, int type, unsigned int Value).
*/
typedef struct _t_loadctrl_cb{
	_t_cbentry 		cbMeasure;		/* Measure the Load */
	_t_cbentry 		cbNotify;		/* Sys Notify the Mod's of Load Message */
}_t_loadctrl_cb;


typedef struct _t_loadctrl_reg{
	unsigned int 		modId;		/* User Custom the Module Id */
	unsigned int 		weight;

	#if 0
	/* 1. Module's Load Control System CbEntry :
	** Memory
	** Timer
	** MsgQ, Queue
	** Socket 
	*/
	_t_loadctrl_cb 	cbSys;
	
	/* 2. Module's Load Control Common CbEntry 
	** Protocol Common Object. 
	** Context Statistics
	** For Example: GW. HNB.
	*/
	_t_loadctrl_cb 	cbCommon;

	/* 3. Module's Load Control Dedicate CbEntry
	** Protocol Dedicate Object. 
	** Context Statistics
	** For Example: UE, RAB, IU-Conn, U-Plane, GTP-U/RTP/Atmi.
	*/
	_t_loadctrl_cb 	cbDedicate;
	#endif
	
	_t_loadctrl_cb 	cbDefault;
}_t_loadctrl_reg;



/*	---------------------------------------------------------------------------
**	The Load Control's Agent & Manager.
*/
typedef struct _t_loadctrl_val{
	unsigned int 		val;
}_t_loadctrl_val;

#define _LOADCTRL_VAL_ASSIGN(pDst, pSrc) 	\
	do{\
		(pDst)->val 		= (pSrc)->val;	\
	}while(0)

#define _LOADCTRL_VAL_INIT(pVal, valInit) 	\
	do{\
		(pVal)->val			= valInit; 		\
	}while(0)

#define _SLOADCTRL_HASH 		4
#define _SLOADCTRL_AGT_MAX  	16
#define _SLOADCTRL_MOD_MAX  	16

typedef struct _t_loadctrl_mod{
	_t_bnode 				modNode;
	_t_bnode 				hashNode;
	unsigned int 			modId;		/* Moudle Id in order to diff each other, hash It....*/
	
	/* Custom Info & Register Callback */
	_t_loadctrl_reg 		modReg;
}_t_loadctrl_mod;

struct _t_loadctrl_manager;

typedef struct _t_loadctrl_agt{
	_t_bnode 			agtNode;
	/* We Could Run in the Seperate Thread or Run Together with the App */
	_t_sysSemB 			wake;
	_t_sysCS			lock;

	int 				bInit;
	int 				bOL;
	int 				index;		/* Used by Manager to Identify Each Agt */
	struct _t_loadctrl_manager * pMan;

	/* Module Active Queue*/
	_t_blist 			modQue;
	_t_blist 			hashQue[_SLOADCTRL_HASH];

	/* Module Pool */
	_t_blist 			modPool;
	_t_loadctrl_mod module[_SLOADCTRL_MOD_MAX];
}_t_loadctrl_agt;



typedef struct _t_loadctrl_manager{
	/* We Could Run in the Seperate Thread or Run Together with the App */
	_t_sysSemB 			wake;
	_t_sysSemM 			lock;

	int 				bInit;
	
	_t_loadctrl_val 	uThrs; 	/* Up Limit */
	_t_loadctrl_val 	dThrs;	/* Down Limit */
	/* Agent Active Queue*/
	_t_blist 			agtQue;

	#if 0
	/* Agent Pool */
	_t_blist 			agtPool;
	_t_loadctrl_agt 	agent[_SLOADCTRL_AGT_MAX];
	#endif
}_t_loadctrl_manager;



extern	int 	SLoadCtrl_ModAdd(_t_loadctrl_agt  * pAgent, _t_loadctrl_reg  * pModReg);
extern	int 	SLoadCtrl_ModDel(_t_loadctrl_agt * pAgent, int modId);

extern	int 	SLoadCtrl_AgtInit(_t_loadctrl_agt * pAgent, int index);
extern	int 	SLoadCtrl_AgtAdd(_t_loadctrl_manager * pMan, _t_loadctrl_agt * pAgent);
extern	int 	SLoadCtrl_AgtDel(_t_loadctrl_manager * pMan, _t_loadctrl_agt * pAgent);
extern	int 	SLoadCtrl_AgtExec(_t_loadctrl_manager * pMan, _t_loadctrl_agt * pAgent, _t_loadctrl_val * pMeter);


extern	int		SLoadCtrl_ManInit(_t_loadctrl_manager * pMan, _t_loadctrl_val * uLimit, _t_loadctrl_val * dLimit);
extern	int 	SLoadCtrl_ManThrsSet(_t_loadctrl_manager * pMan, _t_loadctrl_val * uLimit, _t_loadctrl_val * dLimit);
extern	int 	SLoadCtrl_ManThrsGet(_t_loadctrl_manager * pMan, _t_loadctrl_val * uLimit, _t_loadctrl_val * dLimit);

#ifdef __cplusplus
	}
#endif
									
#endif



